#include "TimTask.h"

/*****************************************************************
 * @brief 初始化任务头
 * @param pstTT 
 * @author lize
 * @date 2025-05-08
*****************************************************************/
void TimTask_Init(TIM_TASK * pstTT)
{
    pstTT->id = 0;
    pstTT->pTaskFun = NULL;
    pstTT->next = NULL;
    pstTT->Last_ID = 1;
    STimInit(&pstTT->stTimer);
}

/*****************************************************************
 * @brief 查找ID任务是否存在
 * @param pTask  头
 * @param ulID   ID
 * @return INT8U 1 存在
 * @author lize
 * @date 2025-05-08
*****************************************************************/
INT8U TimTaskFindID(const TIM_TASK * pTask,INT32U ID)
{
    TIM_TASK * pTemp = pTask->next;

    while (pTemp != NULL)
    {
        if(pTemp->id == ID)
        {
            return 1;
        }
        pTemp = pTemp->next;
    }
    return 0;
}

/*****************************************************************
 * @brief 启动指定ID的软定时器
 * @param pTask 
 * @param id 
 * @return INT8U 1:成功
 * @author lize
 * @date 2025-05-09
*****************************************************************/
INT8U TimTaskStartID(TIM_TASK * pTask,INT32U id)
{
    TIM_TASK * pTemp = pTask->next;

    while (pTemp != NULL)
    {
        if(pTemp->id == id)
        {
            Start(&pTemp->stTimer);
            return 1;
        }
        pTemp = pTemp->next;
    }
    return 0;
}

/*****************************************************************
 * @brief 暂停指定ID的软定时器
 * @param pTask 
 * @param id 
 * @return INT8U 1:成功
 * @author lize
 * @date 2025-05-09
*****************************************************************/
INT8U TimTaskStopID(TIM_TASK * pTask,INT32U id)
{
    TIM_TASK * pTemp = pTask->next;

    while (pTemp != NULL)
    {
        if(pTemp->id == id)
        {
            Stop(&pTemp->stTimer);
            return 1;
        }
        pTemp = pTemp->next;
    }
    return 0;
}

/*****************************************************************
 * @brief 添加任务
 * @param pTask     头
 * @param uiTime    时间
 * @param pfun      待执行函数
 * @return INT32U   0 : Err ; other : 任务的id
 * @author lize
 * @date 2025-05-08
*****************************************************************/
INT32U TimTaskAddTask(TIM_TASK * pTask,INT32U ulTime,void (*pfun)(void))
{
    TIM_TASK *pnew;

    if (!pTask || !pfun) return 0;

    pnew = (TIM_TASK *)malloc(sizeof(TIM_TASK));

    if (pnew == NULL)    return 0;
    
    pnew->next = NULL;
    pnew->pTaskFun = pfun;
    pnew->id = pTask->Last_ID ++;
    STimInit(&pnew->stTimer);
    set(&pnew->stTimer, ulTime);

    TIM_TASK *scan = pTask;
    while (scan->next != NULL)
    {
        scan = scan->next;
    }
    scan->next = pnew;
    return pnew->id;
}

/*****************************************************************
 * @brief 删除任务
 * @param pTask     头
 * @param id        任务ID
 * @return INT8U    1 : 找到对应ID任务并删除
 * @author lize
 * @date 2025-05-08
*****************************************************************/
INT8U TimTaskDelTask(TIM_TASK * pTask,INT32U id)
{
    TIM_TASK *pTemp = pTask->next;
    TIM_TASK *pPrev =  pTask;
    if (pTask == NULL)
        return 0;

    while (pTemp != NULL)
    {
        if (pTemp->id == id)
        {
            if (pTemp->next != NULL)
            {
                pPrev->next = pTemp->next;
            }
            else
            {
                pPrev->next = NULL;
            }
            pTemp->next = NULL;
            free(pTemp);
            return 1;
        }
        pPrev = pTemp;
        pTemp = pTemp->next;
    }
    return 0;
}

/*****************************************************************
 * @brief 定时任务主程序
 * @param pTask 
 * @author lize
 * @date 2025-05-08
*****************************************************************/
void TimTaskHandle(TIM_TASK *pTask)
{
    TIM_TASK  **ppCurrent = &pTask->next;
    while (*ppCurrent != NULL)
    {
        TIM_TASK *current = *ppCurrent;

        if (Timout(&current->stTimer))
        {
            current->pTaskFun(); // 可能删除当前节点

            // 若当前节点未被删除，移动到下一个节点
            if (*ppCurrent == current)
            {
                ppCurrent = &current->next;
                // ppCurrent = &(*ppCurrent)->next;
            }
            else
            {
                /**
                 * 若被删除,ppCurrent 已自动指向新节点.
                 * @bug 考虑ppCurrent此时节点可能已被free(),&(*ppCurrent)->next是野指针,从头开始
                 */
                ppCurrent = &pTask->next;
            }
        }
        else
        {
            ppCurrent = &current->next;
        }
    }
}

/*****************************************************************
函数名称：
函数功能：
输入参数：
返回参数：
修改记录:
日      期		版 本		修改人      内容
2023.9.21		 1.0		 lzj	    初版
2023.11.3        1.1         lzj        结构体版
*****************************************************************/
static void ReadTimBase(TIM_TASK_SOFTTIM *pstTimVal)
{
    INT16U uinTemp;
    INT16U uinTimeStamp;
    if(pstTimVal->uchReadState)
    {
        pstTimVal->uchReadState = 0;
        pstTimVal->uinTimerRec = TASK_GET_TIM_BASE;	    // 进入时取时基初始时间
    }
    uinTimeStamp = TASK_GET_TIM_BASE;
    
    uinTemp = uinTimeStamp - pstTimVal->uinTimerRec;	// 计算差值
    pstTimVal->ulSoftTim += uinTemp;
    pstTimVal->uinTimerRec = uinTimeStamp;		        // 记录本次变化
}

/******************** 初始化 ****************************/
static void STimInit(TIM_TASK_SOFTTIM *pstTimVal)
{
    //ulTmr = 0;
    pstTimVal->uchStop = 1;			// 0:启动 1停止
    pstTimVal->uchReadState = 1;
}

/******************** 设置时间 ****************************/
static void set(TIM_TASK_SOFTTIM *pstTimVal,INT32U ulTime)
{
    pstTimVal->ulInterval = ulTime * TASK_Tim_ratio;
    Start(pstTimVal);
}

/******************** 启动 ****************************/
static void Start(TIM_TASK_SOFTTIM *pstTimVal)
{
    ReadTimBase(pstTimVal);
    pstTimVal->ulTmr = pstTimVal->ulSoftTim;
    pstTimVal->uchStop = 0;
}

/******************** 暂停 ****************************/
static void Stop(TIM_TASK_SOFTTIM *pstTimVal)
{
    pstTimVal->uchStop = 1;
}

/******************** 超时判断 ***************************/
static INT8S Timout(TIM_TASK_SOFTTIM *pstTimVal)
{
    if(pstTimVal->uchStop == 1)
        return 0;
    
    ReadTimBase(pstTimVal);
    INT32U diff = pstTimVal->ulSoftTim - pstTimVal->ulTmr;
    if (diff >= pstTimVal->ulInterval)
    {
        pstTimVal->ulTmr = pstTimVal->ulSoftTim;
        return 1;
    }
    return 0;
}



